package com.itaming.lycheeframework.mybatisflex.config;

import com.itaming.lycheeframework.mybatisflex.autofill.AutoFillProvider;
import com.itaming.lycheeframework.mybatisflex.autofill.BaseEntityInsertListener;
import com.itaming.lycheeframework.mybatisflex.autofill.BaseEntityUpdateListener;
import com.itaming.lycheeframework.mybatisflex.base.BaseEntity;
import com.itaming.lycheeframework.mybatisflex.id.LycheeSnowflakeIdGenerator;
import com.itaming.lycheeframework.support.properties.ExtendedPropertySource;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.keygen.KeyGeneratorFactory;
import com.mybatisflex.core.keygen.KeyGenerators;
import com.mybatisflex.spring.boot.MyBatisFlexCustomizer;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

/**
 * MybatisFlex模块配置类
 *
 * @author A.Ming
 */
@AutoConfiguration
@ExtendedPropertySource({"classpath:lychee-mybatis-flex.yml"})
@RequiredArgsConstructor
public class LycheeMybatisFlexConfiguration {

    /**
     * 自动填充提供者(延迟获取)
     */
    private final ObjectProvider<AutoFillProvider> autoFillProvider;

    /**
     * MyBatisFlexCustomizer
     */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public MyBatisFlexCustomizer lycheeMybatisCustomizer() {
        return globalConfig -> {
            // 注册主键生成器
            registerKeyGenerator();
            // 注册基础实体类自动填充监听器
            registerBaseEntityListener(globalConfig);
        };
    }

    /**
     * 注册主键生成器
     */
    private void registerKeyGenerator() {
        // 覆盖默认提供的雪花算法主键生成器
        KeyGeneratorFactory.register(KeyGenerators.snowFlakeId, new LycheeSnowflakeIdGenerator());
    }

    /**
     * 注册基础实体类自动填充监听器
     */
    private void registerBaseEntityListener(FlexGlobalConfig globalConfig) {
        AutoFillProvider provider = autoFillProvider.getIfAvailable(AutoFillProvider.Impl::new);
        globalConfig.registerInsertListener(new BaseEntityInsertListener(provider), BaseEntity.class);
        globalConfig.registerUpdateListener(new BaseEntityUpdateListener(provider), BaseEntity.class);
    }

}
